import { FormComponentKey } from "@/enums/componentKey"
import { traversalTreeStructure } from '@/utils/index'
import { isArray, isObject } from '@/utils/is'
import dayjs from 'dayjs';
import { propertyFormatByNumber, propertyFormatByPercentage, exc, accMul } from "@/utils/format";

export class FormFormat {
  optionsKeyMap: Record<string, Record<string, string>>
  optionsLabelMap: Record<string, Record<string, string>>
  constructor(
      /** 模块 */
      public fieldTypeMap: Record<string, string>,
      public fieldKeyMap: Record<string, string>,
      public optionsRef: Record<string, string>,
      public componentPropsMap: Record<string, string>,
  ) {
    this.fieldTypeMap = fieldTypeMap
    this.fieldKeyMap = fieldKeyMap
    this.optionsRef = optionsRef;
    const keyMap: Record<string, Record<string, string>> = {},
      labelMap: Record<string, Record<string, string>> = {};
    for (const key in optionsRef) {
      keyMap[key] = {};
      labelMap[key] = {};
      traversalTreeStructure(optionsRef[key], (item) => {
        const childKey = item.value ? item.value : item.id;
        let childLabel = item.label ? item.label : item.name;
        if (childKey) {
          keyMap[key][childKey] = childLabel;
          labelMap[key][childLabel] = childKey;
        }
      });
    }
    // 生成key-value映射表
    this.optionsKeyMap = keyMap;
    this.optionsLabelMap = labelMap;
  }
  updateOptionsKeyMap(optionKey: string, optionInfo) {
    // 更新OptionsMap
    const optionMap: Record<string, string> = {}
    traversalTreeStructure(optionInfo, item => {
      const childKey = item.value ? item.value : item.id
      const childLabel = item.label ? item.label : item.name
      if (childKey) {
        optionMap[childKey] = childLabel
      }
    })
    this.optionsKeyMap[optionKey] = optionMap
  }
  updateSubFormOptionsKeyMap(optionKey: string, optionInfo) {
    // 更新OptionsMap
    const optionMap = { ...this.optionsKeyMap[optionKey] };
    // 合并所有子表单项的选项
    traversalTreeStructure(optionInfo, (item) => {
      const childKey = item.value ? item.value : item.id;
      const childLabel = item.label ? item.label : item.name;
      if (childKey) {
        optionMap[childKey] = childLabel;
      }
    });
    this.optionsKeyMap[optionKey] = optionMap;
  }
  updateOptionsKeyMapLabel(optionKey, childKey, childLabel) {
    // 更新optionsKeyMap, optionsLabelMap
    if (childKey) {
      this.optionsKeyMap[optionKey][childKey] = childLabel;
      this.optionsLabelMap[optionKey][childLabel] = childKey;
    }
  }
  getLabelByValue(componentKey, value, key, subformOption = {}) {
    if (!value) {
      // 用于过滤空值
      return void 0;
    }
    const label = this.optionsKeyMap[componentKey][value] ?? '';
    switch (this.fieldTypeMap[key]) {
      case FormComponentKey.AntdRadioGroupFormPc:
        //判断是否是其他输入
        const otherOption = this.optionsRef[componentKey].find((item) => item.value === value);
        const isOtherOption = otherOption?.other;
        const { isSubform, subformItemLable } = subformOption;
        if (isOtherOption && isSubform) {
          return subformItemLable ? subformItemLable : otherOption.label;
        } else {
          return label;
        }
      default:
        return label ? label : value;
    }
  }
  getValueByLabel(componentKey, label) {
    if (!label) {
      // 用于过滤空值
      return void 0;
    }
    const value = this.optionsLabelMap[componentKey][label] ?? '';
    return value ? value : label;
  }
  getOption(componentKey: string, value: any, subformOption = {}) {
    return { value, label: this.getLabelByValue(`${this.fieldKeyMap[componentKey]}_options`, value, componentKey, subformOption) }
  }
  // 通过fieldKey找到组件配置信息
  getComponentProps(fieldKey) {
    const componentKey = this.fieldKeyMap[fieldKey];
    if (!componentKey || !this.componentPropsMap) {
      return;
    }
    const componentProps = this.componentPropsMap[`${componentKey}_props`];
    return componentProps;
  }
  // 判断组件是否是单选值
  judgeComponentValueIsSingle(fieldKey) {
    const block = this.getComponentProps(fieldKey);
    if (!block) {
      return true;
    }
    const { componentKey, props } = block;
    // 用户组件
    if (componentKey === FormComponentKey.AlUserFormPc) {
      return props.mode?.value === 'combobox';
    }
    // 组织结构
    if (componentKey === FormComponentKey.AlDepartmentFormPc) {
      return !props.multiple?.value;
    }
    const multipleMap = [
      FormComponentKey.AntdCheckboxGroupFormPc,
      FormComponentKey.AntdSelectCheckFormPc,
      FormComponentKey.AntdCascadeFormPc,
    ];
    // 复选、下拉复选、级联
    if (multipleMap.includes(componentKey)) {
      return false;
    }
    return true;
  }
  // 获取日期类组件的日期提交格式
  getDateComponentValueFormat(fieldKey) {
    const block = this.getComponentProps(fieldKey);
    if (!block) {
      return void 0;
    }
    switch (this.fieldTypeMap[fieldKey]) {
      case FormComponentKey.AntdDatePickerFormPc:
      case FormComponentKey.AntdRangePickerFormPc:
        // 原先valueFormat在props配置中，后续删除，直接提交格式设置为'YYYY-MM-DD HH:mm:ss'，为兼容旧数据保留block.props.valueFormat?.value
        return block.valueFormat ?? 'YYYY-MM-DD HH:mm:ss';
      default:
        return void 0;
    }
  }
  // 获取日期类组件的日期格式
  getDateComponentFormat(fieldKey) {
    const block = this.getComponentProps(fieldKey);
    if (!block) {
      return void 0;
    }
    switch (this.fieldTypeMap[fieldKey]) {
      case FormComponentKey.AntdDatePickerFormPc:
      case FormComponentKey.AntdRangePickerFormPc:
        return block.format ?? 'YYYY-MM-DD HH:mm:ss';
      default:
        return void 0;
    }
  }
  setMixedTypeValue(key, value, componentProps, showState = true, subformOption = {}) {
    // 没有字段信息直接返回
    if (!this.fieldTypeMap || !this.fieldTypeMap[key]) {
      return value;
    }
    // 隐藏返回空
    if (!showState) {
      return null;
    }
    switch (this.fieldTypeMap[key]) {
      case FormComponentKey.AntdInputNumberFormPc:
        const { numberFormatType = 'number' } = componentProps;
        if (numberFormatType === 'percent') {
          // 移动端百分比需要除以100
          value = exc(value, 100);
        }

        return value;
      case FormComponentKey.AntdCheckboxGroupFormPc:
      case FormComponentKey.AntdRadioGroupFormPc:
      case FormComponentKey.AntdSelectFormPc:
      case FormComponentKey.AntdSelectCheckFormPc:
      case FormComponentKey.AntdTreeSelectFormPc:
      case FormComponentKey.AntdCascadeFormPc:
      case FormComponentKey.AlUserFormPc:
      case FormComponentKey.AlDepartmentFormPc:
        // Label-Value类型的组件，使用[{label,value}]方式提交
        if (isArray(value)) {
          // 表单重置之后级联选择器的值为[''], 导致存值错误，故放弃使用map方法，改为手动push数组
          const arr = [];
          value.forEach((item) => {
            if (item) {
              if (
                item.hasOwnProperty("value") &&
                item.hasOwnProperty("label")
              ) {
                arr.push(item);
              } else {
                arr.push(this.getOption(key, item, subformOption));
              }
            }
          });
          return arr.length ? arr : null;
        } else {
          const singleValue = this.getOption(key, value, subformOption);
          return singleValue.value ? [singleValue] : null;
        }
      case FormComponentKey.AntdDatePickerFormPc:
        if (!value) {
          return '';
        }
        const dateFormat = this.getDateComponentFormat(key);
        return dayjs(dayjs(value).format(dateFormat), dateFormat).format(
          this.getDateComponentValueFormat(key),
        );
      case FormComponentKey.AntdRangePickerFormPc:
        if (!value || !value?.length) {
          return [];
        }
        const [start, end] = value;
        const rangeFormat = this.getDateComponentFormat(key);
        return [
          start
            ? dayjs(dayjs(start).format(rangeFormat), rangeFormat).format(
              this.getDateComponentValueFormat(key),
            )
            : '',
          end
            ? dayjs(dayjs(end).format(rangeFormat), rangeFormat).format(
              this.getDateComponentValueFormat(key),
            )
            : '',
        ];
      default:
        return value;
    }
  }
  // 返回格式后的数据
  setFormatMixedTypeValue(key, value, componentProps, showState = true) {
    if (!this.fieldTypeMap || !this.fieldTypeMap[key] || !showState) {
      return '';
    }
    switch (this.fieldTypeMap[key]) {
      case FormComponentKey.AntdInputNumberFormPc:
        return this.formatInputNumberValue(value, componentProps);
      default:
        return '';
    }
  }
  formatInputNumberValue(value, componentProps) {
    const {
      numberFormatType = 'number',
      numberCurrencySymbol: currencySymbol = '',
      numberPrecision: accuracy = 0,
      numberThousandthSeparator: thousandthSeparator = false,
    } = componentProps;
    const decimal = '.';
    if (!numberFormatType) {
      return '';
    }
    if (numberFormatType === 'percent') {
      value = exc(value, 100);
      return propertyFormatByPercentage(value, { decimal, accuracy });
    } else {
      return propertyFormatByNumber(value, {
        decimal,
        accuracy,
        currencySymbol,
        thousandthSeparator,
      });
    }
  }
  // 获取数据联动中的混合类型数据的label值
  getMixedTypeLabelValue(key, value, componentProps) {
    switch (this.fieldTypeMap[key]) {
      case FormComponentKey.AntdInputNumberFormPc:
        const { numberFormatType, numberThousandthSeparator } = componentProps;
        if (numberFormatType === 'percent') {
          // 百分比转原始值
          value = exc(value, 100);
        } else if (numberFormatType === 'number') {
          // 千分位转原始值
          if (numberThousandthSeparator) {
            value = String(value).replace(/$s?|(,*)/g, '');
          }
        }
        return Number(value);
      case FormComponentKey.AntdCheckboxGroupFormPc:
      case FormComponentKey.AntdRadioGroupFormPc:
      case FormComponentKey.AntdSelectFormPc:
      case FormComponentKey.AntdSelectCheckFormPc:
      case FormComponentKey.AntdTreeSelectFormPc:
      case FormComponentKey.AntdCascadeFormPc:
      case FormComponentKey.AlUserFormPc:
      case FormComponentKey.AlDepartmentFormPc:
        // Label-Value类型的组件，使用[{label,value}]方式提交
        if (isArray(value)) {
          switch (value.length) {
            case 0:
              return '';
            case 1:
              const singleValue = this.getLabelByValue(
                  `${this.fieldKeyMap[key]}_options`,
                  value[0],
                  key,
              );
              return singleValue ?? '';
            default:
              const arr = [];
              value.forEach((item) => {
                let optionLabel;
                if (item) {
                  optionLabel = this.getLabelByValue(`${this.fieldKeyMap[key]}_options`, item, key);
                  optionLabel && arr.push(optionLabel);
                }
              });
              return arr;
          }
        } else {
          const singleValue = this.getLabelByValue(`${this.fieldKeyMap[key]}_options`, value, key);
          return singleValue ?? '';
        }
      case FormComponentKey.AntdDatePickerFormPc:
        if (!value) {
          return '';
        }
        const dateFormat = this.getDateComponentFormat(key);
        return dayjs(dayjs(value).format(dateFormat), dateFormat).format(
          this.getDateComponentValueFormat(key),
        );
      case FormComponentKey.AntdRangePickerFormPc:
        if (!value || !value?.length) {
          return [];
        }
        const [start, end] = value;
        const rangeFormat = this.getDateComponentFormat(key);
        return [
          start
            ? dayjs(dayjs(start).format(rangeFormat), rangeFormat).format(
              this.getDateComponentValueFormat(key),
            )
            : '',
          end
            ? dayjs(dayjs(end).format(rangeFormat), rangeFormat).format(
              this.getDateComponentValueFormat(key),
            )
            : '',
        ];
      default:
        return value;
    }
  }
  // 根据组件自身格式化配置项处理回显
  getSelfFormatValue(key, value, componentProps) {
    switch (this.fieldTypeMap[key]) {
      case FormComponentKey.AntdInputNumberFormPc:
        const { numberFormatType = 'number' } = componentProps;
        if (value && numberFormatType === 'percent') {
          // 移动端百分比需要除以100
          value = accMul(value, 100);
        }

        return value;
      case FormComponentKey.AntdDatePickerFormPc:
        if (!value) {
          return '';
        }
        return dayjs(value).format(componentProps.extraValueFormat ?? 'YYYY-MM-DD HH:mm:ss');
      case FormComponentKey.AntdRangePickerFormPc:
        if (!value && !value.length) {
          return [];
        }
        const [start, end] = value;
        return end
          ? [
              dayjs(start).format(componentProps.extraValueFormat ?? 'YYYY-MM-DD HH:mm:ss'),
              dayjs(end).format(componentProps.extraValueFormat ?? 'YYYY-MM-DD HH:mm:ss'),
            ]
          : [
              dayjs(start).format(componentProps.extraValueFormat ?? 'YYYY-MM-DD HH:mm:ss'),
              dayjs(start).format(componentProps.extraValueFormat ?? 'YYYY-MM-DD HH:mm:ss'),
            ];
      default:
        return value;
    }
  }
  // 获取数据联动中的不同组件对应的值
  getMixedTypeLinkageValue(key, value, isSingle, format, additionInfo) {
    if (!value) {
      return this.setDefaultValue(value, key, additionInfo);
    }
    switch (this.fieldTypeMap[key]) {
      case FormComponentKey.AntdDatePickerFormPc:
        return dayjs(value).format(format);
      case FormComponentKey.AntdRangePickerFormPc:
        const [start, end] = value;
        return [dayjs(start).format(format), dayjs(end).format(format)];
      case FormComponentKey.AntdInputNumberFormPc:
        // 数字处理格式。
        const componentProps = this.getComponentProps(key);
        if (!componentProps) {
          return value;
        }
        return this.getSelfFormatValue(key, value, componentProps);
      case FormComponentKey.AntdRadioGroupFormPc:
        return this.getValueByLabel(`${this.fieldKeyMap[key]}_options`, value[0].label);
      case FormComponentKey.AntdCheckboxGroupFormPc:
      case FormComponentKey.AntdSelectFormPc:
      case FormComponentKey.AntdSelectCheckFormPc:
      case FormComponentKey.AntdTreeSelectFormPc:
      case FormComponentKey.AntdCascadeFormPc:
        return value.map((item) =>
          this.getValueByLabel(`${this.fieldKeyMap[key]}_options`, item.label),
        );
      case FormComponentKey.AlUploadFormPc:
      case FormComponentKey.AlImageUploadFormPc:
        return value;
      case FormComponentKey.AlUserFormPc:
      case FormComponentKey.AlDepartmentFormPc:
        if (!Array.isArray(value)) {
          return value;
        }
        if (isSingle) {
          return value[0].value ?? value[0].id;
        }
        // Label-Value类型的组件，使用[{label,value}]方式提交
        return value.map((item) => item.value ?? item.id);
      case FormComponentKey.AlUploadFormPc:
      case FormComponentKey.AlImageUploadFormPc:
        return value
      case FormComponentKey.AlSubformFormPc:
        const { originalValue, linkageFormSubformConfig } = additionInfo
        // 参数不完整，暂不处理
        if (
          !originalValue ||
          typeof originalValue !== 'object' ||
          !value ||
          !Array.isArray(value) ||
          !linkageFormSubformConfig
        ) {
          return value
        }
        const result = []
        const linkageFieldMap = {}
        linkageFormSubformConfig.forEach(item => {
          linkageFieldMap[item.currentFieldId] = item.linkageFieldId
        })
        // 遍历联动值
        value.forEach(item => {
          const tempDataInfo = { ...originalValue[0] }
          // 遍历模板字段
          Object.keys(tempDataInfo).forEach(key => {
            // 如果有映射的值，按照映射的值设置
            if (linkageFieldMap[key]) {
              tempDataInfo[key] = this.getMixedTypeLinkageValue(
                key,
                item[linkageFieldMap[key]],
                this.judgeComponentValueIsSingle(key),
                this.getDateComponentValueFormat(key)
              )
            }
          })
          result.push(tempDataInfo)
        })
        return result
      default:
        if (isSingle && Array.isArray(value)) {
          return value[0].label;
        }
        return value;
    }
  }
  // 过滤子表单字段
  filterSubformField(dataList) {
    return (
      dataList &&
      dataList.map((item) => {
        Object.keys(item).forEach((field) => {
          if (field !== 'id' && !this.fieldKeyMap.hasOwnProperty(field)) {
            delete item[field];
          }
        });
        return item;
      })
    );
  }
  // 处理选项值类型组件的回显值问题
  getMixedTypeValue(data, key) {
    if (isObject(data) && data.hasOwnProperty('dataList')) {
      return this.filterSubformField(data.dataList);
    }
    if (!data) {
      return this.setDefaultValue(data, key);
    }
    switch (this.fieldTypeMap[key]) {
      case FormComponentKey.AntdInputNumberFormPc:
        return data;
      case FormComponentKey.AntdRadioGroupFormPc:
        return data[0].value;
      case FormComponentKey.AntdCheckboxGroupFormPc:
      case FormComponentKey.AntdSelectFormPc:
      case FormComponentKey.AntdSelectCheckFormPc:
      case FormComponentKey.AntdTreeSelectFormPc:
      case FormComponentKey.AntdCascadeFormPc:
        return data.map((item) => item.value);
      case FormComponentKey.AlUserFormPc:
      case FormComponentKey.AlDepartmentFormPc:
        return data.map((item) => item.value ?? item.id);
      default:
        return data;
    }
  }
  // 设置组件初始值
  setDefaultValue(data, key, additionInfo) {
    switch (this.fieldTypeMap[key]) {
      case FormComponentKey.AlUploadFormPc:
      case FormComponentKey.AlImageUploadFormPc:
      case FormComponentKey.AntdCheckboxGroupFormPc:
      case FormComponentKey.AntdSelectCheckFormPc:
      case FormComponentKey.AntdCascadeFormPc:
      case FormComponentKey.AntdTreeSelectFormPc:
        return [];
      case FormComponentKey.AlSubformFormPc:
        if (!additionInfo) {
          return data;
        }
        const { originalValue } = additionInfo;
        const result = [];
        const tempDataInfo = originalValue[0];
        // 遍历模板字段
        Object.keys(tempDataInfo).forEach((key) => {
          if (!key.endsWith('_options')) {
            tempDataInfo[key] = this.setDefaultValue('', key);
          }
        });
        result.push(tempDataInfo);
        return result;
      default:
        return data;
    }
  }
  // 获取单选按钮组其他选项值
  getRadioOtherValue(data, key, optionInfo, optionKey) {
    // 获取value
    const value = this.getMixedTypeValue(data, key);
    const filterOption = optionInfo.find((item) => item.value === value);
    if (filterOption?.other) {
      this.updateOptionsKeyMapLabel(optionKey, value, data[0].label);
      return data[0].label;
    }
    return '';
  }
}
